iT邦幫忙

2025 iThome 鐵人賽

DAY 8
0

今日內容:多型(Polymorphism)、getter & setter methods、aggregation、contribution、wrapper classes、ArrayLists


多型(Polymorphism)

繼承相同parent class的多個subclass,在程式內可以先宣告一個parent class出來,接著在執行時期(runtime)依據使用者的輸入或選擇後才決定進行哪個subclass物件的建構

public class Animal{
    void speak(){
        System.out.println("The animal speaks");
    }
}

public class Dog extends Animal{
    @Override
    void speak(){
        System.out.println("The dog says woof");
    }
}

public class Cat extends Animal{
    @Override
    void speak(){
        System.out.println("The cat says meow");
    }
}
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Animal animal; // 先宣告出parent class
        Scanner scanner = new Scanner(System.in);

        System.out.print("You would like a dog or a cat? (1 = dog, 2 = cat): ");
        int choice = scanner.nextInt();

        if(choice == 1){
            animal = new Dog();
            animal.speak(); // The dog says woof
        } 
        else if(choice == 2){
            animal = new Cat();
            animal.speak(); // The cat says meow
        }
        else{
            System.out.println("Invalid input");
        }
        scanner.close();    
    }
}

getter & setter methods

在class中為了保障資料安全,宣告資料型態的前面加上 private 關鍵字就可以讓他在main中不被直接存取(hide)
這時候就需要另外寫 get 和 set funtions(getter and setter)來修改這些private的數值
另外,加上final會使其變得無法被修改,可用於你不想讓其被修改的資料

public class Bank{
    private double balance;
    
    void deposit(double balance){
        if(balance > 0.0){
            this.balance += balance;
        }
    }
    
    void withdraw(double balance){
        if(balance > this.balance){
            this.balance -= balance;
        }
    }
}

aggregation

一個物件中 "has-a" 其他物件,例如Library中會有Book,就算Library不在了,Book也可以被轉移到其他地方,意味著兩者可以同時各自獨立存在

public class Book {
    String title;
    String author;

    Book(String title, String author) {
        this.title = title;
        this.author = author;
    }
    
    void displayInfo() {
        System.out.println("Book: \"" + title + "\" by " + author);
    }
}
public class Library {
    String name;
    Book[] books;
    int bookCount;

    Library(String name, int capacity) {
        this.name = name;
        this.books = new Book[capacity];
        this.bookCount = 0;
    }
    
    void addBook(Book book) {
        if (bookCount < books.length) {
            this.books[bookCount] = book;
            bookCount++;
        } else {
            System.out.println("Library is full");
        }
    }
    
    void listBooks() {
        System.out.println("--- " + name + " ---");
        for (int i = 0; i < bookCount; i++) {
            books[i].displayInfo();
        }
    }
}
public class Main {
    public static void main(String[] args) {
        // Book可以被獨立宣告
        Book book1 = new Book("Effective Java", "Joshua Bloch");
        Book book2 = new Book("Clean Code", "Robert C. Martin");
        
        Library cityLibrary = new Library("LA Library", 5);
        
        // 宣告完Library後將Book加入
        cityLibrary.addBook(book1);
        cityLibrary.addBook(book2);
        
        cityLibrary.listBooks();
    }
}

contribution

一個物件是 "part of" 其他物件,等於A存在於B之中,當B物件不再存在時就再也不可存取到A物件
可以將大型物件切割成很多更小的物件

public class Engine{
    String type;
    
    Engine(String type){
        this.type = type;
    }
}
public class Car{
    String model;
    int year;
    Engine engine;
    
    Car(String model, int year, String engineType){
        this.model = model;
        this.year = year;
        this.engine = new Engine(engineType);
    }
}

Wrapper Classes

用來將基礎資料型態(primitive)轉換成class的形式,可以用在物件中

// Autoboxing
Integer a = new Integer(123); // equal to Integer a = 123;
Double b = new Double(3.14); // = 3.14;
Character c = new Character('$'); // = '$';
Boolean d = new Boolean(true); // = true;
String e = "Pizza"; // 我們平常宣告String就是在用這個方式
    
// Unboxing
int x = a;
double y = b;
char z = c;
// ...

但是為什麼要把它換成wrapper class的形式?
其一是因為可以使用toString函式:

String a = Integer.toString(123);
String b = Double.toString(3.14);
String c = Character.toString('@');
String d = Boolean.toString(false);

String x = a + b + c + d; // 1233.14@false

另外也可以將String轉回去對應的資料型態:

int a = Integer.parseInt("123");
double b = Double.parseDouble("3.14");
char c = "Pizza".charAt(0);  // char沒有parse method,要使用charAt
boolean d = Boolean.parseBoolean("true");

而在Character之下,也有一些utility methods可以用

Character.isLetter(參數); // 檢查是否為a-Z,回傳bool
Character.isUpperCase(參數); // 檢查是否為大寫,回傳bool

不過最主要的原因還是因為要將他轉換成class的形式,在下面ArrayList會提到


ArrayLists

可以用來存物件(包括wrapper class),可以變動大小(動態陣列),用下來的感覺很像C++中的vector

import java.util.ArrayList;

public class Main{
    public static void main(String[] args){
        ArrayList<Integer> list = new ArrayList<>(); // 前面需要提供型態,後面不用
        // 也可以宣告成其他wrapper class: Double, Boolean, String 或者是自己的class
        
        list.add(3); // 很像vector的push_back()
        list.add(1);
        list.add(2);
        
        System.out.println(list); // [3, 1, 2] <- 顯示在terminal的樣子
        
        list.remove(0); // 括號內填index
        
        System.out.println(list); // [1, 2]
        
        list.set(0, 4); // vector的replace(),括號填入(index, 值)
        
        System.out.println(list.get(0)); // 4 用get(index)進行特定位置的資料存取
        System.out.println(list.size()); // 2 用size()取得List大小
    }
}

如果要sort這個ArrayList,需要import另一個函式庫(Collections)

import java.util.Collections;

Collections.sort(list);

結語

今天是接觸Java OOP的第三天,感覺起來越學頭越大,開始出現比較多細微的差距需要理解,並且有想到很多的問題,不過總而言之今天也是快樂學習的一天,明天繼續!/images/emoticon/emoticon30.gif


上一篇
Day 7:Java OOP基礎(二)
下一篇
Day 9:Java 問題與概念釐清
系列文
30天從基礎學起Java,直到做出我的第一個遊戲21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言